package edu.neu.aviator;

import com.alibaba.fastjson.JSONObject;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Slf4j
public class TestController {

    /**
     * POST方法 传入公式，公式中的参数，程序计算和返回结果
     * @param requestMap 一个json格式的请求体，在POST方法的body中传入
     * @return 返回一个json格式的对象，其中键为result的部分即为计算后的结果
     */
    @PostMapping("/test")
    public JSONObject test(@RequestBody Map<String,String> requestMap){
        System.out.println(requestMap);
        String formula = requestMap.get("formula");
        formula = formula.replaceAll("abs", "math.abs"); // abs 替换为 math.abs
        JSONObject result = new JSONObject(true);
        result.fluentPutAll(requestMap);
        try {
            Expression compiledExp = AviatorEvaluator.compile(formula, true); // 编译表达式
            List<String> paramNames = compiledExp.getVariableNames(); // 获取表达式中各个变量的名称
            Map<String, Object> env = new HashMap<>(); // 这个map中存放每个变量和值的对应关系
            for (String paramName : paramNames) {
                //传入的 paramName 参数应为公式里解析出来的参数，即为 basic_param_id
                float paramValue;
                try {
                    paramValue = Float.parseFloat(requestMap.get(paramName));
                    env.put(paramName, paramValue);
                } catch (Exception e){
                    //一般这里出现异常多为忘记传入需要的参数，需要检查传入的参数和公式中的参数是否匹配
                    e.printStackTrace();
                    log.error("当计算以下公式时出现问题：Rule: {}", formula);
                    log.error("原因是：无法获取到这个基本参数的值：basic_param_id = {}", paramName);
                    return result;
                }
            }
            float resultValue = Float.parseFloat(compiledExp.execute(env).toString()); //执行表达式并将结果转为float
            result.put("result", resultValue);
            return result;
        } catch (Exception e) {
            //一般这里出现异常多为表达式编译失败，需要检查表达式语法
            log.error("出现此异常多为表达式编译失败，需要检查表达式语法");
            log.error("但也有可能是别的问题，需要检查StackTrace判断到底是什么异常");
            e.printStackTrace();
            return null;
        }
    }
}
